package org.ninjarope.cinderstained.main.engine.menu;

import java.util.ArrayList;

import org.ninjarope.cinderstained.main.engine.Game;
import org.ninjarope.cinderstained.main.gameplay.Summon;
import org.ninjarope.cinderstained.main.screens.TestingStuff;

import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.BitmapFont.TextBounds;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;

public class MenuItem {
	//
	public final ArrayList<MenuItem> items = new ArrayList<MenuItem>();
	public final Vector2 position;
	public final Rectangle bounds;
	public float radius;
	private Texture tile;
	private TextureRegion reg;
	public String title;
	public boolean active;
	// flag kojim se izvrsava akcija
	public MenuAction action;

	// pocetna tacka menija
	public MenuItem root;

	protected String atlas;
	protected String textureRegion;

	public MenuItem() {
		position = new Vector2();
		bounds = new Rectangle();
		radius = 0;
		active = false;
		title = "Test";
		action = MenuAction.NONE;
	}

	public void define(String sname) {
		String[] name = sname.split(":");
		atlas = name[0];
		textureRegion = name[1];

		reg = Game.get().getFromAtlas(atlas, textureRegion);
		tile = reg.getTexture();
		init(0, 0, reg.getRegionWidth(), reg.getRegionHeight());
	}

	public void init(float x, float y, float width, float height) {
		position.x = x;
		position.y = y;
		bounds.x = x - width / 2;
		bounds.y = y;
		bounds.width = width;
		bounds.height = height;
		radius = (int) width / 2;
	}

	/**
	 * Method for detecting hits
	 * 
	 * @param x
	 * @param y
	 */
	public boolean isHit(float x, float y) {
		active = false;
		if (position.dst(x, y) <= radius) {
			// does item have submenu
			if (items.size() > 0)
				active = true;
			// if item is action
			else {
				perform();
			}
			// checking to see if some of the submenu items was hit
		} else {
			for (MenuItem i : items) {
				if (i.isHit(x, y)) {
					active = true;

				}
			}
		}

		return active;
	}

	public void render(SpriteBatch batch, BitmapFont font) {
		batch.draw(tile, this.bounds.x, this.bounds.y, reg.getRegionX(),
				reg.getRegionY(), reg.getRegionWidth(), reg.getRegionHeight());
		TextBounds textSize = font.getBounds(title);
		font.draw(batch, title, position.x - textSize.width / 2, position.y
				+ textSize.height / 2);

		// System.out.println("rendering menu x: "+position.x
		// +", y: "+position.y);

		if (active) {
			for (MenuItem i : items) {
				// System.out.println("rendering submenu x: "+i.position.x
				// +", y: "+i.position.y);
				i.render(batch, font);
			}
		}
	}

	public void moveTo(float x, float y, OrthographicCamera cam) {
		this.bounds.x = x - this.bounds.width / 2;
		this.bounds.y = y - this.bounds.height / 2;
		this.position.x = x;
		this.position.y = y;
		System.out.println("[0] generating submenu points from "
				+ this.toString());
		System.out.println("[0] object position is " + this.position.x + ", "
				+ this.position.y);
		if (this.items.size() > 0)
			this.generateSubMenuPoints(cam);
	}

	/**
	 * creates circle relative to root menu first submenu uses R=3r, second R=6r
	 * and so on and then returns dots that belong to it with curve distance
	 * beetween them equal 3r
	 * 
	 * @param cam
	 *            -camera used for projecting screen
	 * @return array of submenu item centers
	 */

	public void generateSubMenuPoints(OrthographicCamera cam) {
		float cornerX = 0;
		float cornerY = 0;
		float distance = this.position.dst(0, 0);

		// check for 2nd corner
		float temp = this.position.dst(0, cam.viewportHeight);
		if (distance < temp) {
			distance = temp;
			cornerX = 0;
			cornerY = cam.viewportHeight;
		}

		// check for 3rd corner
		temp = this.position.dst(cam.viewportWidth, 0);
		if (distance < temp) {
			distance = temp;
			cornerX = cam.viewportWidth;
			cornerY = 0;
		}

		// checking 4th corner
		temp = this.position.dst(cam.viewportWidth, cam.viewportHeight);
		if (distance < temp) {
			distance = temp;
			cornerX = cam.viewportWidth;
			cornerY = cam.viewportHeight;
		}

		System.out.println("distance is: " + distance);
		System.out
				.println("most distant corner is " + cornerX + ", " + cornerY);
		// we now determined furthest corner
		// now searching the point on which vector intersects circumferance
		Vector2 tempV = new Vector2(cornerX - position.x, cornerY - position.y);
		System.out.println("pre normalizacije vektor je " + tempV.x + ", "
				+ tempV.y);
		tempV = TestingStuff.normalize(tempV);
		System.out.println("posle normalizacije vektor je " + tempV.x + ", "
				+ tempV.y);
		// now we determine point by multiplaying with range
		tempV.x = (float) (tempV.x * 2.5 * radius);
		tempV.y = (float) (tempV.y * 2.5 * radius);

		tempV.x = position.x + tempV.x;
		tempV.y = position.y + tempV.y;

		System.out.println("arc midle point is " + tempV.x + ", " + tempV.y);
		// /now we have a dot that seperates arc in half we need to find next
		// point

		System.out.println("[1] menu has " + this.items.size() + " submenu");
		float arc = (float) ((((2 * radius * this.items.size()) + ((this.items
				.size() - 1) * radius)) / 2) * 2.5 / 3);

		System.out.println("[2] arc length is " + arc);
		// starting point of arc
		Vector2 startPoint = moveArcCounterClockwise(tempV.x, tempV.y,
				(float) (2.5 * radius), arc);

		System.out.println("[3] arc starting point " + startPoint.x + ", "
				+ startPoint.y);
		boolean first = true;
		// setting position for all submenu items
		System.out.println("Recalculating submenu");
		System.out.println("[4] menu still has " + this.items.size()
				+ " submenus");
		for (MenuItem i : this.items) {
			Vector2 point;
			// first item will be moved for r, rest of them will be moved for 3
			// * r
			if (first) {
				point = moveArcClockwise(startPoint.x, startPoint.y,
						(float) (2.5 * radius), radius);
				i.moveTo(point.x, point.y, cam);
				startPoint = point;
				first = false;
				System.out.println("[5] first point is " + startPoint.x + ", "
						+ startPoint.y);
			} else {
				point = moveArcClockwise(startPoint.x, startPoint.y,
						3 * radius, 3 * radius);
				i.moveTo(point.x, point.y, cam);
				startPoint = point;
			}

			System.out.println("x: " + point.x + ", y: " + point.y);
		}
		System.out.println("[6] menu finished rendering " + items.size()
				+ " submenus");
	}

	/**
	 * Function for calculating next point in arc
	 * 
	 * @param x
	 *            -x cordinate for exsisting arc point
	 * @param y
	 *            - y cordinate for exsisting arc point
	 * @param r
	 *            - circle radius
	 * @param d
	 *            - distance along the arc from given point
	 * @return returns a point that is on arc distance d away from given point
	 */
	public Vector2 moveArcClockwise(float x, float y, float r, float d) {
		// angle
		// double a = (360 * d) / (2 * r * Math.PI);

		double a = d / r;
		// a = Math.toDegrees(a);

		System.out.println("Found angle is : " + a);

		// calculating point
		float tempX = x - this.position.x;
		float tempY = y - this.position.y;
		// calculating point
		Vector2 temp = new Vector2(0, 0);
		temp.x = (float) ((tempX * Math.cos(a)) - (tempY * Math.sin(a)));
		temp.y = (float) ((tempY * Math.cos(a)) + (tempX * Math.sin(a)));
		;

		System.out.println("new found point is:" + temp.x + "," + temp.y);
		temp.x += this.position.x;
		temp.y += this.position.y;
		System.out.println("new found incremented point:" + temp.x + ","
				+ temp.y);
		return temp;

	}

	/**
	 * Function for calculating next point in arc
	 * 
	 * @param x
	 *            -x cordinate for exsisting arc point
	 * @param y
	 *            - y cordinate for exsisting arc point
	 * @param r
	 *            - circle radius
	 * @param d
	 *            - distance along the arc from given point
	 * @return returns a point that is on arc distance d away from given point
	 */

	public Vector2 moveArcCounterClockwise(float x, float y, float r, float d) {
		// angle
		// double a = -(360 * d) / (2 * r * Math.PI);

		double a = -d / r;
		// a = Math.toDegrees(a);

		System.out.println("Found angle is : " + a);
		float tempX = x - this.position.x;
		float tempY = y - this.position.y;
		// calculating point
		Vector2 temp = new Vector2(0, 0);
		temp.x = (float) ((tempX * Math.cos(a)) - (tempY * Math.sin(a)));
		temp.y = (float) ((tempY * Math.cos(a)) + (tempX * Math.sin(a)));
		;

		temp.x += this.position.x;
		temp.y += this.position.y;
		return temp;

	}

	protected void perform() {
		// if tower creation is selected
		if (action == MenuAction.TOWER) {
			Summon summonTemp = TestingStuff.summonPool.request();
			summonTemp.define("world:you");
			summonTemp.attackSpeed.current = 1;
			summonTemp.range.current = 150;
			summonTemp.dmg.current = 2;
			if (this.root == null) {
				summonTemp.moveTo(position.x, position.y);
			} else {
				summonTemp.moveTo(root.position.x, root.position.y);
			}

			TestingStuff.summons.add(summonTemp);
			TestingStuff.renderList.add(summonTemp);
			// if waypoint creation is selected
		} else if (action == MenuAction.WAYPOINT) {
			if (this.root == null) {
				TestingStuff.map.waypoints.add(new Vector2(position.x,
						position.y));
			} else {
				TestingStuff.map.waypoints.add(new Vector2(root.position.x,
						root.position.y));
			}
		}
	}
}